<!doctype html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="javascript,CommonJS,AMD,RequireJS,Browserify,UMD,Webpack,ES6,Rollup,JSPM," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />






<meta name="description" content="本文转载自：众成翻译译者：网络埋伏纪事链接：http://www.zcfy.cc/article/1560原文：https://medium.com/@sungyeol.choi/javascript-module-module-loader-module-bundler-es6-module-confused-yet-6343510e7bde#.d40hvgkqf


砖模块和依赖
你是否是">
<meta property="og:type" content="article">
<meta property="og:title" content="JavaScript 模块简史(转载)">
<meta property="og:url" content="http://chrisrc.me/2016/10/29/js-module-history/index.html">
<meta property="og:site_name" content="山中，山外与俯瞰">
<meta property="og:description" content="本文转载自：众成翻译译者：网络埋伏纪事链接：http://www.zcfy.cc/article/1560原文：https://medium.com/@sungyeol.choi/javascript-module-module-loader-module-bundler-es6-module-confused-yet-6343510e7bde#.d40hvgkqf


砖模块和依赖
你是否是">
<meta property="og:image" content="https://cdn-images-1.medium.com/max/2000/1*68FMiPIAUMmxaDexaJLesA.png">
<meta property="og:image" content="https://cdn-images-1.medium.com/max/600/1*oPUjUJwA7FamPbG48wh5TQ.png">
<meta property="og:image" content="https://cdn-images-1.medium.com/max/600/1*0Xvs9xTXSvRHbPMsZ79xeA.jpeg">
<meta property="og:image" content="https://cdn-images-1.medium.com/max/800/1*YGkqF-sTQA4SW8GpAvg1bg.png">
<meta property="og:image" content="https://cdn-images-1.medium.com/max/600/1*mxULJDkVDpCbQDAnB7y1vg.png">
<meta property="og:updated_time" content="2016-12-17T07:29:29.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="JavaScript 模块简史(转载)">
<meta name="twitter:description" content="本文转载自：众成翻译译者：网络埋伏纪事链接：http://www.zcfy.cc/article/1560原文：https://medium.com/@sungyeol.choi/javascript-module-module-loader-module-bundler-es6-module-confused-yet-6343510e7bde#.d40hvgkqf


砖模块和依赖
你是否是">
<meta name="twitter:image" content="https://cdn-images-1.medium.com/max/2000/1*68FMiPIAUMmxaDexaJLesA.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    sidebar: {"position":"left","display":"post"},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://chrisrc.me/2016/10/29/js-module-history/"/>





  <title> JavaScript 模块简史(转载) | 山中，山外与俯瞰 </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  










  
  
    
  

  <div class="container one-collumn sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">山中，山外与俯瞰</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle">一次永不停止的探索之旅</p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-dcos">
          <a href="/dcos" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-book"></i> <br />
            
            DC/OS
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="st-search-show-outputs">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <form class="site-search-form">
  <input type="text" id="st-search-input" class="st-search-input st-default-search-input" />
</form>

<script type="text/javascript">
  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
    (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
    e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');

  _st('install', 'R9GcmhBwxpsAGLNCsquZ','2.0.0');
</script>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
  <link itemprop="mainEntityOfPage" href="http://chrisrc.me/2016/10/29/js-module-history/">

  <span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <meta itemprop="name" content="chrisrc">
    <meta itemprop="description" content="">
    <meta itemprop="image" content="/images/avatar.gif">
  </span>

  <span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="山中，山外与俯瞰">
    <span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
      <img style="display:none;" itemprop="url image" alt="山中，山外与俯瞰" src="">
    </span>
  </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                JavaScript 模块简史(转载)
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2016-10-29T16:10:18+08:00">
                2016-10-29
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
              <span class="post-meta-divider">|</span>
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JavaScript/" itemprop="url" rel="index">
                    <span itemprop="name">JavaScript</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <a href="/2016/10/29/js-module-history/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count ds-thread-count" data-thread-key="2016/10/29/js-module-history/" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          

          
          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <blockquote>
<p>本文转载自：<a href="http://www.zcfy.cc" target="_blank" rel="external">众成翻译</a><br>译者：<a href="http://www.zcfy.cc/@bigshaw" target="_blank" rel="external">网络埋伏纪事</a><br>链接：<a href="http://www.zcfy.cc/article/1560" target="_blank" rel="external">http://www.zcfy.cc/article/1560</a><br>原文：<a href="https://medium.com/@sungyeol.choi/javascript-module-module-loader-module-bundler-es6-module-confused-yet-6343510e7bde#.d40hvgkqf" target="_blank" rel="external">https://medium.com/@sungyeol.choi/javascript-module-module-loader-module-bundler-es6-module-confused-yet-6343510e7bde#.d40hvgkqf</a></p>
</blockquote>
<p><img src="https://cdn-images-1.medium.com/max/2000/1*68FMiPIAUMmxaDexaJLesA.png" alt=""></p>
<p>砖模块和依赖</p>
<p>你是否是 JavaScript 新手，搞不清楚模块、模块加载器和模块打包器？或者你已经写了 JavaScript 一段时间，但是没法掌握模块的一些行话？你是否听过像 CommonJS、AMD、Browserify、SystemJS、Webpack、JSPM 等等术语，但是不理解为什么我们需要它们？</p>
<p>我将解释它们是什么，它们要解决什么问题，以及如何解决问题。<br><a id="more"></a></p>
<h2 id="示例应用程序"><a href="#示例应用程序" class="headerlink" title="示例应用程序"></a>示例应用程序</h2><p><img src="https://cdn-images-1.medium.com/max/600/1*oPUjUJwA7FamPbG48wh5TQ.png" alt=""></p>
<p>应用程序运行界面</p>
<p>在本文中，会用一个简单的应用程序来阐述模块的概念。这个应用程序要在浏览器上显示数组的和，它由四个函数和一个 <code>index.html</code> 文件组成。</p>
<p><img src="https://cdn-images-1.medium.com/max/600/1*0Xvs9xTXSvRHbPMsZ79xeA.jpeg" alt=""><br> 函数的依赖示意图</p>
<p><code>main</code> 函数计算数组中数字的和，然后把答案显示给 <code>span#answer</code>。<code>sum</code> 函数依赖于两个函数：<code>add</code> 和 <code>reduce</code>。<code>add</code> 函数做它名字所做的，把两个数相加。<code>reduce</code> 函数遍历数组，并且调用 <code>iteratee</code> 回调函数。</p>
<p>花点时间理解下面的代码。我会多次使用相同的函数。</p>
<p>0 - index.html</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>JS Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span></div><div class="line">      The Answer is</div><div class="line">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">"answer"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<p>1 - main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values)</div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div></pre></td></tr></table></figure>
<p>2 - sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> reduce(arr, add);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>3 - add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a, b</span>) </span>&#123;</div><div class="line">  <span class="keyword">return</span> a + b;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>4 - reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">  <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">    length = arr.length,</div><div class="line">    memo = arr[index];</div><div class="line">  <span class="keyword">for</span>(index += <span class="number">1</span>; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index])</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>我们来看看如何将这些代码片段放在一起，来创建一个应用程序。</p>
<h2 id="使用内嵌脚本"><a href="#使用内嵌脚本" class="headerlink" title="使用内嵌脚本"></a>使用内嵌脚本</h2><p>内嵌脚本就是在<code>&lt;script&gt;&lt;/script&gt;</code>标记之间添加 JavaScript 代码。这是我开始学 JavaScript 时的做法。我相信大多数 JavaScript 开发者在其生命里至少这样做过一次。</p>
<p>这是开始的好方法。不需要操心外部文件或者依赖。但是这也导致了不可维护的代码，因为：</p>
<ul>
<li>缺乏代码可重用性：如果需要添加另一个页面，并需要本页上的一些功能，我们就不得不复制粘贴代码。</li>
<li>缺乏依赖解析：你必须保证 <code>main</code> 函数之前就有 <code>add</code>、<code>reduce</code> 和 <code>sum</code> 函数。</li>
<li>命名空间污染：所有的函数诶变量将都驻留在全局作用域。</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="comment">&lt;!-- index.html --&gt;</span></div><div class="line"></div><div class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>JS Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span></div><div class="line">      The Answer is</div><div class="line">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">"answer"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></div><div class="line"></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span><span class="javascript"></span></div><div class="line">      <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a, b</span>) </span>&#123;</div><div class="line">        <span class="keyword">return</span> a + b;</div><div class="line">      &#125;</div><div class="line">      <span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">        <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">          length = arr.length,</div><div class="line">          memo = arr[index];</div><div class="line">        <span class="keyword">for</span>(index += <span class="number">1</span>; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">          memo = iteratee(memo, arr[index])</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">return</span> memo;</div><div class="line">      &#125;</div><div class="line">      <span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">        <span class="keyword">return</span> reduce(arr, add);</div><div class="line">      &#125;</div><div class="line">      <span class="comment">/* Main Function */</span></div><div class="line">      <span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line">      <span class="keyword">var</span> answer = sum(values)</div><div class="line">      <span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div><div class="line">    <span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<h2 id="使用Script-标记链接外部-JavaScript-文件"><a href="#使用Script-标记链接外部-JavaScript-文件" class="headerlink" title="使用Script 标记链接外部 JavaScript 文件"></a>使用<code>Script</code> 标记链接外部 JavaScript 文件</h2><p>这是嵌入脚本的一个自然过渡。现在我们将大段的 JavaScript 分成更小的段，并用 <code>&lt;script src=“...”&gt;&lt;/script&gt;</code> 标记加载它们。</p>
<p>通过将文件分离到多个 JavaScript 文件，就可以重用代码了。我们不再需要在不同的网页之间复制和粘贴代码，只需要将文件用 <code>script</code> 标记就可以了。这种方法虽然更好，但是依然有如下问题：</p>
<ul>
<li>缺乏依赖解析：文件的顺序很重要。你要负责在 main.js 文件之前包含 <code>add.js</code>、<code>reduce.js</code> 和 <code>sum.js</code> 文件。</li>
<li>全局命令空间污染：所有的函数和变量依然在全局作用域中。</li>
</ul>
<p>0 - index.html</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">&lt;!DOCTYPE html&gt;</div><div class="line">&lt;html&gt;</div><div class="line">  &lt;head&gt;</div><div class="line">    &lt;meta charset="UTF-8"&gt;</div><div class="line">    &lt;title&gt;JS Modules&lt;/title&gt;</div><div class="line">  &lt;/head&gt;</div><div class="line">  &lt;body&gt;</div><div class="line">    &lt;h1&gt;</div><div class="line">      The Answer is</div><div class="line">      &lt;span id="answer"&gt;&lt;/span&gt;</div><div class="line">    &lt;/h1&gt;</div><div class="line"></div><div class="line">    &lt;script type="text/javascript" src="./add.js"&gt;&lt;/script&gt;</div><div class="line">    &lt;script type="text/javascript" src="./reduce.js"&gt;&lt;/script&gt;</div><div class="line">    &lt;script type="text/javascript" src="./sum.js"&gt;&lt;/script&gt;</div><div class="line">    &lt;script type="text/javascript" src="./main.js"&gt;&lt;/script&gt;</div><div class="line">  &lt;/body&gt;</div></pre></td></tr></table></figure>
<p>1 - add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//add.js</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a, b</span>) </span>&#123;</div><div class="line">  <span class="keyword">return</span> a + b;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>2 - reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//reduce.js</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">  <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">    length = arr.length,</div><div class="line">    memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index])</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>3 - sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//sum.js</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> reduce(arr, add);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>4 - main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"> <span class="comment">// main.js</span></div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values)</div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div></pre></td></tr></table></figure>
<h2 id="模块对象和-IIFE（模块模式）"><a href="#模块对象和-IIFE（模块模式）" class="headerlink" title="模块对象和 IIFE（模块模式）"></a>模块对象和 IIFE（模块模式）</h2><p>通过使用模块对象和<a href="https://en.wikipedia.org/wiki/Immediately-invoked_function_expression" target="_blank" rel="external">立即运行的函数表达式（IIFE）</a>，我们可以减少全局命名空间污染。在本方法中，我们只暴露了一个对象给全局作用域，该对象包含了应用程序中所需的所有方法和值。在本例中，我们只暴露了 <code>myApp</code> 对象给全局作用域。所有的函数将都被放到 <code>myApp</code> 对象中。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 01  my-app.js</span></div><div class="line"><span class="keyword">var</span> myApp = &#123;&#125;;</div></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 02 - add.js</span></div><div class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">  myApp.add = <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>&#123;</div><div class="line">    <span class="keyword">return</span> a + b;</div><div class="line">  &#125;  </div><div class="line">&#125;)();</div></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 03 - reduce.js</span></div><div class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">  myApp.reduce = <span class="function"><span class="keyword">function</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">    <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">      length = arr.length,</div><div class="line">      memo = arr[index];</div><div class="line">  </div><div class="line">    index += <span class="number">1</span>;</div><div class="line">    <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">      memo = iteratee(memo, arr[index])</div><div class="line">    &#125;</div><div class="line">    <span class="keyword">return</span> memo;</div><div class="line">  &#125;  </div><div class="line">&#125;)();</div></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 04 - sum.js</span></div><div class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">  myApp.sum = <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> myApp.reduce(arr, myUtil.add);</div><div class="line">  &#125;  </div><div class="line">&#125;)();</div></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 05 - main.js</span></div><div class="line">(<span class="function"><span class="keyword">function</span>(<span class="params">app</span>)</span>&#123;</div><div class="line">  <span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line">  <span class="keyword">var</span> answer = app.sum(values)</div><div class="line">  <span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div><div class="line">&#125;)(myApp);</div></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 06 - index.html</span></div><div class="line">&lt;!DOCTYPE html&gt;</div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span></div><div class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>JS Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span></div><div class="line">      The Answer is</div><div class="line">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">"answer"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></div><div class="line"></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"./my-app.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"./add.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"./reduce.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"./sum.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"./main.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<p>注意除了 <code>my-app.js</code> 之外，其它每个文件都被封装成 IIFE 格式。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; <span class="comment">/*... your code goes here ...*/</span> &#125;)();</div></pre></td></tr></table></figure>
<p>通过将每个文件封装为 IIFE，所有的局部变量就都待在函数作用域内。所以，函数中的所有变量将都会待在函数作用域内，而不会污染全局作用域。</p>
<p>通过将 <code>add</code>、<code>reduce</code> 和 <code>sum</code> 函数附加在 <code>myApp</code> 对象上，从而对外暴露它们。并且我们可以像这样，通过引用 <code>myApp</code> 来访问这些函数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">myApp.add(<span class="number">1</span>,<span class="number">2</span>);</div><div class="line">myApp.sum([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]);</div><div class="line">myApp.reduce(add, value);</div></pre></td></tr></table></figure>
<p>我们还可以通过 IIFE 参数，传递 <code>myApp</code> 全局对象，就像 <code>main.js</code> 文件中所示一样。通过将该对象作为参数传递给 IIFE，我们就可以为该对象选择一个较短的别名。而我们的代码会更简短点。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">(<span class="function"><span class="keyword">function</span>(<span class="params">obj</span>)</span>&#123;</div><div class="line">  <span class="comment">// obj 是一个新的 veryLongNameOfGlobalObject</span></div><div class="line">&#125;)(veryLongNameOfGloablObject);</div></pre></td></tr></table></figure>
<p>这与前例相比有很大的提升了。很多流行的 JavaScript 都会用这种模式。比如 jQuery，它暴露一个全局对象 <code>$</code>，所有 jQuery 函数都挂在 <code>$</code> 对象之下。</p>
<p>但是，这依然不算是完美的解决方案。这种方案依然会遇到上节相同的问题：</p>
<ul>
<li>缺乏依赖解析：文件的顺序依然重要，<code>myApp.js</code> 必须出现在所有其它文件之前，<code>main.js</code> 必须处在所有其它库文件之后。</li>
<li>全局命令空间污染：现在全局变量的数量变成了 1，但是还不是 0 。</li>
</ul>
<h2 id="CommonJS"><a href="#CommonJS" class="headerlink" title="CommonJS"></a>CommonJS</h2><p>在 2009 年，出现了关于将 JavaScript 带到服务器端的讨论，因而 ServerJS 诞生了。之后，ServerJS 更名为 CommonJS。</p>
<p>CommonJS 并非一个 JavaScript 库，而是一个标准化组织，像 ECMA 或者 W3C 一样。ECMA 定义了 JavaScript 语言规范。W3C 定义了 JavaScript Web API，比如 DOM 和 DOM 事件。CommonJS 的目标是为 Web 服务器、桌面和命令行应用程序定义一套通用的 API。</p>
<p>CommonJS 还定义了模块 API 。因为在服务器应用程序中没有 HTML 页面，也没有 script 标记，所以就得有一些清晰的模块 API。模块需要暴露（<strong>export</strong>）给其它模块使用，并且是可访问的（<strong>import</strong>）。它的输出模块语法像这样的：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// add.js</span></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a, b</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> a+b;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>上述代码定义和输出了一个模块。代码保存在 <code>add.js</code> 文件中。</p>
<p>要使用或者导入 <code>add</code> 模块，需要 <code>require</code> 函数用文件名或者模块名为参数。如下的语法描述如何导入一个模块到代码中：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> add = <span class="built_in">require</span>(‘./add’);</div></pre></td></tr></table></figure>
<p>如果你曾经在 NodeJS 上写过代码，那么这种语法看起来会很熟悉。这是因为 NodeJS 实现了 CommonJS 风格的模块 API。</p>
<h2 id="AMD（异步模块定义）"><a href="#AMD（异步模块定义）" class="headerlink" title="AMD（异步模块定义）"></a>AMD（异步模块定义）</h2><p>CommonJS 风格的模块定义的问题是，它不是异步的。当调用 <code>var add=require(‘add’);</code>时，系统会暂停，直到模块准备好了。这意味着在所有模块正在加载时，这行代码会冻结浏览器。所以这可能不是定义浏览器端模块的最佳方式。<br>为了把服务器端用的模块语法转换给浏览器端用，CommonJS 提出了几种模块格式。其中之一，即 “Module/Transfer/C“，后来成为<a href="https://github.com/amdjs/amdjs-api/blob/master/AMD.md" target="_blank" rel="external">异步模块定义（AMD</a>）。</p>
<p>AMD 的格式如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">define([‘add’, ‘reduce’], <span class="function"><span class="keyword">function</span>(<span class="params">add, reduce</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;...&#125;;</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p><code>define</code> 函数（或者关键字）用依赖列表和一个回调函数做参数。回调函数的参数与数组中的依赖有相同的次序。这等于导入模块。而回调函数会返回一个值，该值就是输出的值。</p>
<p>CommonJS 和 AMD 解决了模块模式剩下的两个问题：<em>依赖解析</em>和<em>全局作用域污染</em>，现在我们只需要注意每个模块或者文件的依赖，并且不再有全局作用域污染。</p>
<h2 id="RequireJS"><a href="#RequireJS" class="headerlink" title="RequireJS"></a>RequireJS</h2><p>AMD 可以把我们从浏览器应用程序中的 script 标记黑洞和全局污染中解救出来。那么，我们该如何使用它呢？这里 RequireJS 就可以帮助我们了。RequireJS 是一个 JavaScript 模块加载器。它可以帮助我们按需异步加载模块。</p>
<p>尽管 RequireJS 的名字中含有 <code>require</code>，但是它的目标却并非要去支持 CommonJS 的 <code>require</code> 语法。有了 RequireJS，我们就可以编写 AMD 风格的模块。</p>
<p>在编写自己的应用程序之前，你将不得不从 <a href="http://requirejs.org/docs/start.html" target="_blank" rel="external">RequireJS 网站</a> 下载 <code>require.js</code> 文件。如下代码是用 RequireJS 编写的示例应用程序。</p>
<p><em>AMD 风格的示例应用程序</em></p>
<p>0 - index.html</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>JS Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span></div><div class="line">      The Answer is</div><div class="line">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">"answer"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></div><div class="line"></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">data-main</span>=<span class="string">"main"</span> <span class="attr">src</span>=<span class="string">"require.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<p>1 - main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// main.js</span></div><div class="line">define([<span class="string">'sum'</span>], <span class="function"><span class="keyword">function</span>(<span class="params">sum</span>)</span>&#123;</div><div class="line">  <span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line">  <span class="keyword">var</span> answer = sum(values)</div><div class="line">  <span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div><div class="line">&#125;)</div></pre></td></tr></table></figure>
<p>2 - sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// sum.js</span></div><div class="line">define([<span class="string">'add'</span>, <span class="string">'reduce'</span>], <span class="function"><span class="keyword">function</span>(<span class="params">add, reduce</span>)</span>&#123;</div><div class="line">  <span class="keyword">var</span> sum = <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> reduce(arr, add);</div><div class="line">  &#125;;</div><div class="line"></div><div class="line">  <span class="keyword">return</span> sum;</div><div class="line">&#125;)</div></pre></td></tr></table></figure>
<p>3 - add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// add.js</span></div><div class="line">define([], <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">  <span class="keyword">var</span> add = <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> a + b;</div><div class="line">  &#125;;</div><div class="line"></div><div class="line">  <span class="keyword">return</span> add;</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>4 - reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// reduce.js</span></div><div class="line">define([], <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line">  <span class="keyword">var</span> reduce = <span class="function"><span class="keyword">function</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">    <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">      length = arr.length,</div><div class="line">      memo = arr[index];</div><div class="line"></div><div class="line">    index += <span class="number">1</span>;</div><div class="line">    <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">      memo = iteratee(memo, arr[index])</div><div class="line">    &#125;</div><div class="line">    <span class="keyword">return</span> memo;</div><div class="line">  &#125;</div><div class="line"></div><div class="line">  <span class="keyword">return</span> reduce;</div><div class="line">&#125;)</div></pre></td></tr></table></figure>
<p>注意在 <code>index.html</code> 中只有一个 script 标记。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&lt;script data-main=<span class="string">"main"</span> src=<span class="string">"require.js"</span>&gt;<span class="xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></div></pre></td></tr></table></figure>
<p>这个标记加载 <code>require.js</code> 库到页面，<code>data-main</code> 属性告诉 RequieJS 应用程序的入口点在哪里。默认情况下，它假定所有文件都有 <code>.js</code> 扩展名，所以省略 <code>.js</code> 文件扩展名是可以的。在 RequireJS 加载了 <code>main.js</code> 文件之后，就会加载该文件的依赖，以及依赖的依赖，等等。Chrome 浏览器的开发者工具会显示所有文件被以如下顺序加载：</p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*YGkqF-sTQA4SW8GpAvg1bg.png" alt=""></p>
<p>浏览器加载 <code>index.html</code>，<code>index.html</code> 又加载 <code>require.js</code>。剩下的文件及其依赖都是由 <code>require.js</code> 负责加载。</p>
<p>RequireJS 和 AMD 解决了我们以前所遇到的所有问题。但是，它有带来了其它一些不怎么严重的问题：</p>
<ul>
<li>AMD 语法很古怪。因为所有东西都封装在 <code>define</code> 函数内，代码就有一些额外的缩进。对于小文件来说，这不是啥问题，但是对于大的代码库来说，就可能是精神上的疲惫。</li>
<li>数组中的依赖列表必须与函数的参数列表匹配。如果有很多依赖，就很难维护依赖的次序。如果模块中有几十个依赖，后来又要从中间删除一个，那么就很难找到匹配的模块和参数。</li>
<li>在当前浏览器下（HTTP 1.1），加载很多小文件会降低性能。</li>
</ul>
<h2 id="Browserify"><a href="#Browserify" class="headerlink" title="Browserify"></a>Browserify</h2><p>因为以上原因，有些人就想用 CommonJS 语法来替换。但是，CommonJS 语法用于服务器和同步的，对吧？这时 Browserify 就来解救我们了！有了 Browserify，我们就可以在浏览器应用程序中使用 CommonJS 模块。Browserify 是一个<em>模块打包器</em>，它遍历代码的依赖树，将依赖树中的所有模块打包成一个文件。</p>
<p>RequireJS 是一个 JS 库，但是 Browserify 是一个命令行工具，需要 NodeJS 和 NPM 来按住那个它。如果系统中安装了 NodeJS，就可以用如下命令来安装 Browserify：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm install -g browserify</div></pre></td></tr></table></figure>
<p>下面我们来看看用 CommonJS 语法写的示例应用程序。</p>
<p>0 - index.html</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>JS Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span></div><div class="line">      The Answer is</div><div class="line">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">"answer"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></div><div class="line"></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"bundle.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<p>1 - main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//main.js</span></div><div class="line"><span class="keyword">var</span> sum = <span class="built_in">require</span>(<span class="string">'./sum'</span>);</div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values)</div><div class="line"></div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div></pre></td></tr></table></figure>
<p>2 - sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//sum.js</span></div><div class="line"><span class="keyword">var</span> reduce = <span class="built_in">require</span>(<span class="string">'./reduce'</span>);</div><div class="line"><span class="keyword">var</span> add = <span class="built_in">require</span>(<span class="string">'./add'</span>);</div><div class="line"></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> reduce(arr, add);</div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>3 - add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//add.js</span></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a,b</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> a + b;</div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>4 - reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//reduce.js</span></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">  <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">    length = arr.length,</div><div class="line">    memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index])</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>你可能注意到，在 <code>index.html</code> 文件中，script 标记加载 <code>bundle.js</code>，但是 <code>bundle.js</code> 文件在哪里？一旦我们执行了如下命令，Browserify 就会为我们生成这个文件：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ brwoserify main.js -o bundle.js</div></pre></td></tr></table></figure>
<p>Browserify 解析 <code>main.js</code> 中的 <code>require()</code> 函数调用，并遍历项目中的依赖树。然后将依赖树打包到一个文件中。</p>
<p>如下是Browserify 生成的 <code>bundle.js</code> 文件的代码：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">e</span>(<span class="params">t,n,r</span>)</span>&#123;<span class="function"><span class="keyword">function</span> <span class="title">s</span>(<span class="params">o,u</span>)</span>&#123;<span class="keyword">if</span>(!n[o])&#123;<span class="keyword">if</span>(!t[o])&#123;<span class="keyword">var</span> a=<span class="keyword">typeof</span> <span class="built_in">require</span>==<span class="string">"function"</span>&amp;&amp;<span class="built_in">require</span>;<span class="keyword">if</span>(!u&amp;&amp;a)<span class="keyword">return</span> a(o,!<span class="number">0</span>);<span class="keyword">if</span>(i)<span class="keyword">return</span> i(o,!<span class="number">0</span>);<span class="keyword">var</span> f=<span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">"Cannot find module '"</span>+o+<span class="string">"'"</span>);<span class="keyword">throw</span> f.code=<span class="string">"MODULE_NOT_FOUND"</span>,f&#125;<span class="keyword">var</span> l=n[o]=&#123;<span class="attr">exports</span>:&#123;&#125;&#125;;t[o][<span class="number">0</span>].call(l.exports,<span class="function"><span class="keyword">function</span>(<span class="params">e</span>)</span>&#123;<span class="keyword">var</span> n=t[o][<span class="number">1</span>][e];<span class="keyword">return</span> s(n?n:e)&#125;,l,l.exports,e,t,n,r)&#125;<span class="keyword">return</span> n[o].exports&#125;<span class="keyword">var</span> i=<span class="keyword">typeof</span> <span class="built_in">require</span>==<span class="string">"function"</span>&amp;&amp;<span class="built_in">require</span>;<span class="keyword">for</span>(<span class="keyword">var</span> o=<span class="number">0</span>;o&lt;r.length;o++)s(r[o]);<span class="keyword">return</span> s&#125;)(&#123;<span class="number">1</span>:[<span class="function"><span class="keyword">function</span>(<span class="params">require,module,exports</span>)</span>&#123;</div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a,b</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> a + b;</div><div class="line">&#125;;</div><div class="line"></div><div class="line">&#125;,&#123;&#125;],<span class="number">2</span>:[<span class="function"><span class="keyword">function</span>(<span class="params">require,module,exports</span>)</span>&#123;</div><div class="line"><span class="keyword">var</span> sum = <span class="built_in">require</span>(<span class="string">'./sum'</span>);</div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values)</div><div class="line"></div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div><div class="line"></div><div class="line">&#125;,&#123;<span class="string">"./sum"</span>:<span class="number">4</span>&#125;],<span class="number">3</span>:[<span class="function"><span class="keyword">function</span>(<span class="params">require,module,exports</span>)</span>&#123;</div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">  <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">    length = arr.length,</div><div class="line">    memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index])</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;;</div><div class="line"></div><div class="line">&#125;,&#123;&#125;],<span class="number">4</span>:[<span class="function"><span class="keyword">function</span>(<span class="params">require,module,exports</span>)</span>&#123;</div><div class="line"><span class="keyword">var</span> reduce = <span class="built_in">require</span>(<span class="string">'./reduce'</span>);</div><div class="line"><span class="keyword">var</span> add = <span class="built_in">require</span>(<span class="string">'./add'</span>);</div><div class="line"></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> reduce(arr, add);</div><div class="line">&#125;;</div><div class="line"></div><div class="line">&#125;,&#123;<span class="string">"./add"</span>:<span class="number">1</span>,<span class="string">"./reduce"</span>:<span class="number">3</span>&#125;]&#125;,&#123;&#125;,[<span class="number">2</span>]);</div></pre></td></tr></table></figure>
<p>我们不必一行一行理解这个打包文件，只是要注意，所有熟悉的代码、main 文件及其所有依赖，都包含在这个文件中。</p>
<h2 id="UMD-—-只会让你更糊涂"><a href="#UMD-—-只会让你更糊涂" class="headerlink" title="UMD — 只会让你更糊涂"></a>UMD — 只会让你更糊涂</h2><p>现在我们已经学习了全局模块对象、CommonJS 和 AMD 风格的模块，并且有很多库可以帮助我们要么用 CommonJS，要么用 AMD。但是，如果我们正编写一个模块，并要把它部署到互联网上该怎么办？我们到底需该用哪种风格写代码呢？</p>
<p>用三种不同的模块类型，即全局模块对象、CommonJS 和 AMD，都是可以的。但是我们就不得不维护三种不同的文件，用户就不得不识别他们正在下载的模块的类型。</p>
<p>通用模块定义 UMD（Universal Module Definition）是用来解决这个特殊问题的。本质上，UMD 是一套用来识别当前环境支持的模块风格的 if/else 语句。如下是用 UMD 风格编写的 <code>sum</code> 模块：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//sum.umd.js</span></div><div class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">root, factory</span>) </span>&#123;</div><div class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> define === <span class="string">'function'</span> &amp;&amp; define.amd) &#123;</div><div class="line">        <span class="comment">// AMD</span></div><div class="line">        define([<span class="string">'add'</span>, <span class="string">'reduce'</span>], factory);</div><div class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> exports === <span class="string">'object'</span>) &#123;</div><div class="line">        <span class="comment">// Node, CommonJS-like</span></div><div class="line">        <span class="built_in">module</span>.exports = factory(<span class="built_in">require</span>(<span class="string">'add'</span>), <span class="built_in">require</span>(<span class="string">'reduce'</span>));</div><div class="line">    &#125; <span class="keyword">else</span> &#123;</div><div class="line">        <span class="comment">// Browser globals (root is window)</span></div><div class="line">        root.sum = factory(root.add, root.reduce);</div><div class="line">    &#125;</div><div class="line">&#125;(<span class="keyword">this</span>, <span class="function"><span class="keyword">function</span> (<span class="params">add, reduce</span>) </span>&#123;</div><div class="line">    <span class="comment">// private methods</span></div><div class="line"></div><div class="line">    <span class="comment">// exposed public methods</span></div><div class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>) </span>&#123;</div><div class="line">      <span class="keyword">return</span> reduce(arr, add);</div><div class="line">    &#125;</div><div class="line">&#125;));</div></pre></td></tr></table></figure>
<h2 id="ES6-模块语法"><a href="#ES6-模块语法" class="headerlink" title="ES6 模块语法"></a>ES6 模块语法</h2><p>JavaScript 全局模块对象、CommonJS、AMD 和 UMD，太多选择了。现在也许你会问，下一个项目我该用哪一个呢？答案是一个都不用。</p>
<p>JavaScript 语言中并没有内置模块系统。这正是我们有如此多输入和输出模块的不同方式的原因。但是这种情况最近得到改变了。在 ES6 规范中，模块已经成为 JavaScript 的一部分。所以这个问题的答案是，如果想让项目不会过时，就得用 ES6 模块语法。</p>
<p>ES6 用 <code>import</code> 和 <code>export</code> 关键字来输入和输出模块。如下是用 ES6 模块语法编写的示例应用程序。</p>
<p>01 - main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// main.js</span></div><div class="line"><span class="keyword">import</span> sum <span class="keyword">from</span> <span class="string">"./sum"</span>;</div><div class="line"></div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values);</div><div class="line"></div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer</div></pre></td></tr></table></figure>
<p>02 - sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// sum.js</span></div><div class="line"><span class="keyword">import</span> add <span class="keyword">from</span> <span class="string">'./add'</span>;</div><div class="line"><span class="keyword">import</span> reduce <span class="keyword">from</span> <span class="string">'./reduce'</span>;</div><div class="line"></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> reduce(arr, add);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>03 - add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// add.js</span></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a,b</span>)</span>&#123;</div><div class="line">  <span class="keyword">return</span> a + b;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>04 - reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//reduce.js</span></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">  <span class="keyword">let</span> index = <span class="number">0</span>,</div><div class="line">  length = arr.length,</div><div class="line">  memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index]);</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>关于 ES6 模块有很多广告语：ES6 模块语法是简洁的；ES6 模块将统治 JavaScript 世界；ES6 模块是未来。。。但是不幸的是，有个问题，浏览器还没有为这个新语法做好准备。在本文编写时，只有 Chrome 浏览器支持 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import" target="_blank" rel="external">import</a> 语句。即使到了大多数浏览器都支持 <code>import</code> 和 <code>export</code> 的时候，如果应用程序必须支持老的浏览器，我们就还会遇到一个问题。</p>
<p>幸运的是，现在已经有很多工具可以用了，这些工具让我们现在就可以用 ES6 模块语法。</p>
<h2 id="Webpack"><a href="#Webpack" class="headerlink" title="Webpack"></a>Webpack</h2><p>Webpack 是一个模块打包器。就像 Browserify 一样，它会遍历依赖树，然后将其打包到一到多个文件。如果 Webpack 与 Browserify 完全相同，那么我们为什么依然需要另一个模块打包器呢？Webpack 可以处理CommonJS、AMD 和 ES6 模块，并且它带来了更大的灵活性和很酷的一些功能，比如：</p>
<ul>
<li>代码分离：如果有多个 app 共享相同的模块。Webpack 可以将代码打包到两到多个文件。例如，如果有两个 app：app1 和 app2，二者都共用很多模块。如果用 Browserify 的话，就有 app1.js 和 app2.js，两个文件都要包含所有依赖模块。但是如果是用 Webpack 的话，我们就可以创建 app1.js、app2.js 和 shared-lib.js。是的，我们必须从 html 页面中加载两个文件。但是有了哈希文件名、浏览器缓存和 CDN，就可以降低初始加载时间。</li>
<li>加载器：用自定义加载器，可以加载任何文件到源文件中。用 <code>require()</code> 语法，不仅仅可以加载 JavaScript 文件，还可以加载 CSS、CoffeeScript、Sass、Less、HTML模板、图像，等等。</li>
<li>插件：Webpack 插件可以在打包写入到文件之前对它进行操作。有很多社区创建的插件。例如，给打包代码添加注释，添加 Source map，将打包文件分离成块等等。</li>
<li>WebpackDevServer 是一个开发服务器，它可以在源代码改变被检测到时自动打包源代码，并刷新浏览器。通过提供代码的即时反馈，从而加快开发过程。</li>
</ul>
<p>下面我们来看看如何用 Webpack 创建示例应用程序。Webpack 需要一点引导工作和配置。</p>
<p>因为 Webpack 是 JavaScript 命令行工具，所以需要先安装上 NodeJS 和 NPM。装好 NPM 后，执行如下命令初始化项目：</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ mkdir project; <span class="built_in">cd</span> project</div><div class="line">$ npm init -y</div><div class="line">$ npm install -D webpack webpack-dev-server</div></pre></td></tr></table></figure>
<p>你需要为 wepack 写一个配置文件 webpack.config.js。文件中至少需要 entry 和 output 两个字段。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">module</span>.exports = &#123;</div><div class="line">   <span class="attr">entry</span>: ‘./app/main.js’,</div><div class="line">   <span class="attr">output</span>: &#123;</div><div class="line">       <span class="attr">filename</span>: ‘bundle.js’</div><div class="line">   &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>打开 ‘package.json” 文件，在 ‘script’ 字段后添加如下行：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="string">"scripts"</span>: &#123;</div><div class="line">    <span class="string">"start"</span>: <span class="string">"webpack-dev-server -progress -colors"</span>,</div><div class="line">    <span class="string">"build"</span>: <span class="string">"webpack"</span></div><div class="line"> &#125;,</div></pre></td></tr></table></figure>
<p>现在在 ‘project/app’ 目录下添加所有 JavaScript 模块，在 ‘project’ 目录下添加 index.html。</p>
<p>01 - index.html</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">&lt;!DOCTYPE html&gt;</div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span></div><div class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>JS Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></div><div class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></div><div class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span></div><div class="line">      The Answer is</div><div class="line">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">id</span>=<span class="string">"answer"</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></div><div class="line">    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></div><div class="line"></div><div class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"bundle.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div><div class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></div><div class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></div></pre></td></tr></table></figure>
<p>02 - webpack.config.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">module</span>.exports = &#123;</div><div class="line">  <span class="attr">entry</span>: <span class="string">'./app/main.js'</span>,</div><div class="line">  <span class="attr">output</span>: &#123;</div><div class="line">    <span class="attr">path</span>: <span class="string">'./dist'</span>,</div><div class="line">    <span class="attr">filename</span>: <span class="string">'bundle.js'</span></div><div class="line">  &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>03 - package.json</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">&#123;</div><div class="line">  <span class="string">"name"</span>: <span class="string">"jsmodules"</span>,</div><div class="line">  <span class="string">"version"</span>: <span class="string">"1.0.0"</span>,</div><div class="line">  <span class="string">"description"</span>: <span class="string">""</span>,</div><div class="line">  <span class="string">"main"</span>: <span class="string">"main.js"</span>,</div><div class="line">  <span class="string">"scripts"</span>: &#123;</div><div class="line">    <span class="string">"start"</span>: <span class="string">"webpack-dev-server --progress --colors"</span>,</div><div class="line">    <span class="string">"build"</span>: <span class="string">"webpack"</span></div><div class="line">  &#125;,</div><div class="line">  <span class="string">"keywords"</span>: [],</div><div class="line">  <span class="string">"author"</span>: <span class="string">""</span>,</div><div class="line">  <span class="string">"license"</span>: <span class="string">"ISC"</span>,</div><div class="line">  <span class="string">"devDependencies"</span>: &#123;</div><div class="line">    <span class="string">"webpack"</span>: <span class="string">"^1.12.14"</span>,</div><div class="line">    <span class="string">"webpack-dev-server"</span>: <span class="string">"^1.14.1"</span></div><div class="line">  &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>04 - app-add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// app/add.js</span></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a,b</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> a + b;</div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>05 - app-reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// app/reduce.js</span></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">reduce</span>(<span class="params">arr, iteratee</span>) </span>&#123;</div><div class="line">  <span class="keyword">var</span> index = <span class="number">0</span>,</div><div class="line">    length = arr.length,</div><div class="line">    memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index])</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;;</div></pre></td></tr></table></figure>
<p>06 - app-sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// app/sum.js</span></div><div class="line">define([<span class="string">'./reduce'</span>, <span class="string">'./add'</span>], <span class="function"><span class="keyword">function</span>(<span class="params">reduce, add</span>)</span>&#123;</div><div class="line">  sum =  <span class="function"><span class="keyword">function</span>(<span class="params">arr</span>)</span>&#123;</div><div class="line">    <span class="keyword">return</span> reduce(arr, add);</div><div class="line">  &#125;</div><div class="line"></div><div class="line">  <span class="keyword">return</span> sum;</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>07 - app-main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// app/main.js</span></div><div class="line"><span class="keyword">var</span> sum = <span class="built_in">require</span>(<span class="string">'./sum'</span>);</div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values)</div><div class="line"></div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div></pre></td></tr></table></figure>
<p>注意 <code>add.js</code> 和 <code>reduce.js</code> 是用 CommonJS 风格写的，而 <code>sum.js</code> 是用 AMD 风格写的。 Webpack 默认是可以处理 CommonJS 和 AMD。如果你用 ES6 模块，就需要安装和配置 ‘babel loader’。</p>
<p>所有文件准备好，就可以运行你的应用程序了。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm start</div></pre></td></tr></table></figure>
<p>打开浏览器，把 URL 指向 <a href="http://localhost:8080/webpack-dev-server/" target="_blank" rel="external">http://localhost:8080/webpack-dev-server/</a>.</p>
<p><img src="https://cdn-images-1.medium.com/max/600/1*mxULJDkVDpCbQDAnB7y1vg.png" alt=""></p>
<p> webpack dev server in action</p>
<p>此时，你可以打开你喜欢的编辑器编辑代码。保存文件时，浏览器会自动刷新以显示修改后的结果。</p>
<p>这里你可能会注意到一件事情，就是找不到 <code>dist/bundle.js</code> 文件。这是因为 Webpack Dev Server 会创建打包文件，但是不会写入到文件系统中，而是放在内存中。</p>
<p>如果要部署，就得创建打包文件。可以键入如下命令，创建 <code>bundle.js</code> 文件：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm run build</div></pre></td></tr></table></figure>
<p>如果有兴趣学习更多的 Webpack 技巧，请参考 <a href="https://webpack.github.io/docs/" target="_blank" rel="external">Webpack 文档页</a>。</p>
<h2 id="Rollup-2015-年-5-月"><a href="#Rollup-2015-年-5-月" class="headerlink" title="Rollup (2015 年 5 月)"></a>Rollup (2015 年 5 月)</h2><p>将一个大的 JavaScript 库包含进来，只是为了用它函数中的少数几个，你是否有这样的经历？Rollup 是另一个 JavaScript ES6 模块打包器。与 Browserify 和 Webpak 不同，rollup 值包含在项目中用到的代码。如果有大模块，带有很多函数，但是你只是用到少数几个，rollup 只会将需要的函数包含到打包文件中，从而显著减少打包文件大小。</p>
<p>Rollup 可以被用作为命令行工具。如果有 NodeJS 和 NPM，那么就可以用如下命令安装 rollup：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm install -g rollup</div></pre></td></tr></table></figure>
<p>Rollup 可以与任何类型的模块风格一起工作。但是，推荐使用 ES6 模块风格，这样就可以利用 tree-shaking 功能。如下是用 ES6 编写的示例应用程序代码：</p>
<p>01 - add.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> add = <span class="function">(<span class="params">a,b</span>) =&gt;</span> a + b;</div><div class="line"><span class="keyword">let</span> sub = <span class="function">(<span class="params">a,b</span>) =&gt;</span> a - b;</div><div class="line"></div><div class="line"><span class="keyword">export</span>  &#123; add, sub &#125;;</div></pre></td></tr></table></figure>
<p>02 - reduce.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// reduce.js</span></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> (arr, iteratee) =&gt; &#123;</div><div class="line">  <span class="keyword">let</span> index = <span class="number">0</span>,</div><div class="line">  length = arr.length,</div><div class="line">  memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index]);</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>03 - sum.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// sum.js</span></div><div class="line"><span class="keyword">import</span> &#123; add &#125; <span class="keyword">from</span> <span class="string">'./add'</span>;</div><div class="line"><span class="keyword">import</span> reduce <span class="keyword">from</span> <span class="string">'./reduce'</span>;</div><div class="line"></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> (arr) =&gt; reduce(arr, add);</div></pre></td></tr></table></figure>
<p>04 - main.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// main.js</span></div><div class="line"><span class="keyword">import</span> sum <span class="keyword">from</span> <span class="string">"./sum"</span>;</div><div class="line"></div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values);</div><div class="line"></div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div></pre></td></tr></table></figure>
<p>注意，在 <code>add</code> 模块中，我引入了另一个函数 <code>sub()</code>。但是该函数在应用程序中并没有用到。</p>
<p>现在我们用 rollup 将这些代码打包：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ rollup main.js -o bundle.js</div></pre></td></tr></table></figure>
<p>这会生成像如下的 <code>bundle.js</code> 文件：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> add = <span class="function">(<span class="params">a,b</span>) =&gt;</span> a + b;</div><div class="line"></div><div class="line"><span class="keyword">var</span> reduce = <span class="function">(<span class="params">arr, iteratee</span>) =&gt;</span> &#123;</div><div class="line">  <span class="keyword">let</span> index = <span class="number">0</span>,</div><div class="line">  length = arr.length,</div><div class="line">  memo = arr[index];</div><div class="line"></div><div class="line">  index += <span class="number">1</span>;</div><div class="line">  <span class="keyword">for</span>(; index &lt; length; index += <span class="number">1</span>)&#123;</div><div class="line">    memo = iteratee(memo, arr[index]);</div><div class="line">  &#125;</div><div class="line">  <span class="keyword">return</span> memo;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">var</span> sum = <span class="function">(<span class="params">arr</span>) =&gt;</span> reduce(arr, add);</div><div class="line"></div><div class="line"><span class="keyword">var</span> values = [ <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ];</div><div class="line"><span class="keyword">var</span> answer = sum(values);</div><div class="line"></div><div class="line"><span class="built_in">document</span>.getElementById(<span class="string">"answer"</span>).innerHTML = answer;</div></pre></td></tr></table></figure>
<p>这里我们可以看到 <code>sub()</code> 函数并没有包含在这个打包文件中。</p>
<h2 id="SystemJS"><a href="#SystemJS" class="headerlink" title="SystemJS"></a>SystemJS</h2><p>SystemJS 是一个通用的模块加载器，它能在浏览器或者 NodeJS 上动态加载模块，并且支持 CommonJS、AMD、全局模块对象和 ES6 模块。通过使用插件，它不仅可以加载 JavaScript，还可以加载 CoffeeScript 和 TypeScript。</p>
<p>SystemJS 的另一个优点是，它建立在 ES6 模块加载器之上，所以它的语法和 API 在将来很可能是语言的一部分，这会让我们的代码更不会过时。</p>
<p>要异步输入一个模块，可以用如下语法：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">System.import(‘<span class="built_in">module</span>-name’);</div></pre></td></tr></table></figure>
<p>然后我们可以用配置 API 来配置 SystemJS 的行为：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">System.config(&#123;</div><div class="line">  <span class="attr">transplier</span>: ‘babel’,</div><div class="line">  <span class="attr">baseURL</span>: ‘/app’</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>上面的配置会让 SystemJS 使用 babel 作为 ES6 模块的编译器，并且从 <code>/app</code> 目录加载模块。</p>
<p>随着现代 JavaScript 应用程序变得越来越大，越来越复杂，开发工作流也是如此。所以我们不仅仅模块加载器，还得去寻找开发服务器、生产的模块打包器以及第三方模块的包管理器。</p>
<h2 id="JSPM"><a href="#JSPM" class="headerlink" title="JSPM"></a>JSPM</h2><p>JSPM 是 JavaScript 开发工具的瑞士军刀，它是既是包管理器，又是模块加载器，又是模块打包器。</p>
<p>现代 JavaScript 开发很少只是需要自己的模块，绝大部分时候，我们还需要第三方模块。使用 JSPM，我们可以使用如下的命令，从 NPM 或者 Github 安装第三方模块：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">jspm install npm:package-name or github:package/name</div></pre></td></tr></table></figure>
<p>上述命令会从 <code>npm</code> 或者 <code>github</code> 下载包，并将包安装到 <code>jspm_packages</code> 目录。</p>
<p>在开发模式下，我们可以使用 <code>jspm-server</code>。像 Webpack Dev Server 一样，它会检测代码改变，重新加载浏览器来显示改变。与 Webpack Dev Server 不同的是，jspm-server 用的是 SystemJS 模块加载器。所以，每次它检测了文件的改变时，不会将所有文件读取来打包，而是只加载页面所需要的模块。</p>
<p>在部署时，肯定要打包代码。JSPM 带有打包器，可以用如下命令对代码打包：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">jspm bundle main.js bundle.js</div></pre></td></tr></table></figure>
<p>在幕后，JSPM 用 rollup 作为它的打包器。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>我希望本文给了足够的信息来理解 JavaScript 模块的词汇。现在你也许会问，下一个项目我应该用什么呢？不幸的是，我回答不了这个问题。现在你有能力开始自己的探索。希望本文能让你更容易理解我提到的有关工具的文档和文章。</p>
<p>本文所有的代码示例都可以在 <a href="https://github.com/sungthecoder/js-modules-examples" target="_blank" rel="external">这个 Github 仓库</a>中找到。如有任何疑问，请在下面留言。</p>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>


    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/javascript/" rel="tag"># javascript</a>
          
            <a href="/tags/CommonJS/" rel="tag"># CommonJS</a>
          
            <a href="/tags/AMD/" rel="tag"># AMD</a>
          
            <a href="/tags/RequireJS/" rel="tag"># RequireJS</a>
          
            <a href="/tags/Browserify/" rel="tag"># Browserify</a>
          
            <a href="/tags/UMD/" rel="tag"># UMD</a>
          
            <a href="/tags/Webpack/" rel="tag"># Webpack</a>
          
            <a href="/tags/ES6/" rel="tag"># ES6</a>
          
            <a href="/tags/Rollup/" rel="tag"># Rollup</a>
          
            <a href="/tags/JSPM/" rel="tag"># JSPM</a>
          
        </div>
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2016/10/24/mesos-local-universe/" rel="next" title="在DCOS上搭建本地Universe仓库">
                <i class="fa fa-chevron-left"></i> 在DCOS上搭建本地Universe仓库
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2016/11/17/mesos-docker-registry/" rel="prev" title="在DCOS中搭建私有容器仓库">
                在DCOS中搭建私有容器仓库 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
        <div class="ds-share flat" data-thread-key="2016/10/29/js-module-history/"
     data-title="JavaScript 模块简史(转载)"
     data-content=""
     data-url="http://chrisrc.me/2016/10/29/js-module-history/">
  <div class="ds-share-inline">
    <ul  class="ds-share-icons-16">

      <li data-toggle="ds-share-icons-more"><a class="ds-more" href="javascript:void(0);">分享到：</a></li>
      <li><a class="ds-weibo" href="javascript:void(0);" data-service="weibo">微博</a></li>
      <li><a class="ds-qzone" href="javascript:void(0);" data-service="qzone">QQ空间</a></li>
      <li><a class="ds-qqt" href="javascript:void(0);" data-service="qqt">腾讯微博</a></li>
      <li><a class="ds-wechat" href="javascript:void(0);" data-service="wechat">微信</a></li>

    </ul>
    <div class="ds-share-icons-more">
    </div>
  </div>
</div>
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
      <div class="ds-thread" data-thread-key="2016/10/29/js-module-history/"
           data-title="JavaScript 模块简史(转载)" data-url="http://chrisrc.me/2016/10/29/js-module-history/">
      </div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/avatar.gif"
               alt="chrisrc" />
          <p class="site-author-name" itemprop="name">chrisrc</p>
          <p class="site-description motion-element" itemprop="description"></p>
        </div>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">69</span>
              <span class="site-state-item-name">日志</span>
            </a>
          </div>

          
            <div class="site-state-item site-state-categories">
              <a href="/categories">
                <span class="site-state-item-count">21</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            <div class="site-state-item site-state-tags">
              <a href="/tags">
                <span class="site-state-item-count">162</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/christtrc" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://twitter.com/chrisrc" target="_blank" title="Twitter">
                  
                    <i class="fa fa-fw fa-twitter"></i>
                  
                  Twitter
                </a>
              </span>
            
          
        </div>

        
        
          <div class="cc-license motion-element" itemprop="license">
            <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" target="_blank">
              <img src="/images/cc-by-nc-sa.svg" alt="Creative Commons" />
            </a>
          </div>
        

        
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#示例应用程序"><span class="nav-number">1.</span> <span class="nav-text">示例应用程序</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#使用内嵌脚本"><span class="nav-number">2.</span> <span class="nav-text">使用内嵌脚本</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#使用Script-标记链接外部-JavaScript-文件"><span class="nav-number">3.</span> <span class="nav-text">使用Script 标记链接外部 JavaScript 文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模块对象和-IIFE（模块模式）"><span class="nav-number">4.</span> <span class="nav-text">模块对象和 IIFE（模块模式）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#CommonJS"><span class="nav-number">5.</span> <span class="nav-text">CommonJS</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AMD（异步模块定义）"><span class="nav-number">6.</span> <span class="nav-text">AMD（异步模块定义）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#RequireJS"><span class="nav-number">7.</span> <span class="nav-text">RequireJS</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Browserify"><span class="nav-number">8.</span> <span class="nav-text">Browserify</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#UMD-—-只会让你更糊涂"><span class="nav-number">9.</span> <span class="nav-text">UMD — 只会让你更糊涂</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#ES6-模块语法"><span class="nav-number">10.</span> <span class="nav-text">ES6 模块语法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Webpack"><span class="nav-number">11.</span> <span class="nav-text">Webpack</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Rollup-2015-年-5-月"><span class="nav-number">12.</span> <span class="nav-text">Rollup (2015 年 5 月)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#SystemJS"><span class="nav-number">13.</span> <span class="nav-text">SystemJS</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JSPM"><span class="nav-number">14.</span> <span class="nav-text">JSPM</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#总结"><span class="nav-number">15.</span> <span class="nav-text">总结</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy;  2015 - 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">
     
      <a href="mailto:chrisrc@qq.com">chrisrc</a> 
    
  </span>
  <span class="author"> &nbsp; QQ: 58122705 </span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Mist
  </a>
</div>


        

        
      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  



  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script>



  

  
    
  

  <script type="text/javascript">
    var duoshuoQuery = {short_name:"chrisrc"};
    (function() {
      var ds = document.createElement('script');
      ds.type = 'text/javascript';ds.async = true;
      ds.id = 'duoshuo-script';
      ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
      ds.charset = 'UTF-8';
      (document.getElementsByTagName('head')[0]
      || document.getElementsByTagName('body')[0]).appendChild(ds);
    })();
  </script>

  
    
    
    <script src="/lib/ua-parser-js/dist/ua-parser.min.js?v=0.7.9"></script>
    <script src="/js/src/hook-duoshuo.js"></script>
  








  
  

  

  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
<script>
(function(){
   var src = (document.location.protocol == "http:") ? "http://js.passport.qihucdn.com/11.0.1.js?ed903ab05fbc5fa64d95e4bfbf3d3a04":"https://jspassport.ssl.qhimg.com/11.0.1.js?ed903ab05fbc5fa64d95e4bfbf3d3a04";
   document.write('<script src="' + src + '" id="sozz"><\/script>');
})();
</script>

  


</body>
</html>
